@soybeanjs/cli 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +15 -553
- package/dist/index.d.ts +15 -0
- package/dist/index.mjs +16 -552
- package/dist/lint-staged.config.d.ts +3 -0
- package/package.json +3 -6
package/dist/index.cjs
CHANGED
|
@@ -12,10 +12,7 @@ const promises = require('fs/promises');
|
|
|
12
12
|
const EE = require('events');
|
|
13
13
|
const Stream = require('stream');
|
|
14
14
|
const stringdecoder = require('string_decoder');
|
|
15
|
-
const
|
|
16
|
-
const ofetch = require('ofetch');
|
|
17
|
-
const dayjs = require('dayjs');
|
|
18
|
-
const convertGitmoji = require('convert-gitmoji');
|
|
15
|
+
const changelog = require('@soybeanjs/changelog');
|
|
19
16
|
const versionBumpp = require('bumpp');
|
|
20
17
|
|
|
21
18
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
@@ -38,55 +35,15 @@ const actualFS__namespace = /*#__PURE__*/_interopNamespaceCompat(actualFS);
|
|
|
38
35
|
const EE__default = /*#__PURE__*/_interopDefaultCompat(EE);
|
|
39
36
|
const Stream__default = /*#__PURE__*/_interopDefaultCompat(Stream);
|
|
40
37
|
const stringdecoder__default = /*#__PURE__*/_interopDefaultCompat(stringdecoder);
|
|
41
|
-
const cliProgress__default = /*#__PURE__*/_interopDefaultCompat(cliProgress);
|
|
42
|
-
const dayjs__default = /*#__PURE__*/_interopDefaultCompat(dayjs);
|
|
43
38
|
const versionBumpp__default = /*#__PURE__*/_interopDefaultCompat(versionBumpp);
|
|
44
39
|
|
|
45
|
-
const version = "0.5.
|
|
40
|
+
const version = "0.5.3";
|
|
46
41
|
|
|
47
42
|
async function execCommand(cmd, args, options) {
|
|
48
43
|
const { execa } = await import('execa');
|
|
49
44
|
const res = await execa(cmd, args, options);
|
|
50
45
|
return res?.stdout?.trim() || "";
|
|
51
46
|
}
|
|
52
|
-
function notNullish(v) {
|
|
53
|
-
return v !== null && v !== void 0;
|
|
54
|
-
}
|
|
55
|
-
function partition(array, ...filters) {
|
|
56
|
-
const result = new Array(filters.length + 1).fill(null).map(() => []);
|
|
57
|
-
array.forEach((e, idx, arr) => {
|
|
58
|
-
let i = 0;
|
|
59
|
-
for (const filter of filters) {
|
|
60
|
-
if (filter(e, idx, arr)) {
|
|
61
|
-
result[i].push(e);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
i += 1;
|
|
65
|
-
}
|
|
66
|
-
result[i].push(e);
|
|
67
|
-
});
|
|
68
|
-
return result;
|
|
69
|
-
}
|
|
70
|
-
function groupBy(items, key, groups = {}) {
|
|
71
|
-
for (const item of items) {
|
|
72
|
-
const v = item[key];
|
|
73
|
-
groups[v] = groups[v] || [];
|
|
74
|
-
groups[v].push(item);
|
|
75
|
-
}
|
|
76
|
-
return groups;
|
|
77
|
-
}
|
|
78
|
-
function capitalize(str) {
|
|
79
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
80
|
-
}
|
|
81
|
-
function join(array, glue = ", ", finalGlue = " and ") {
|
|
82
|
-
if (!array || array.length === 0)
|
|
83
|
-
return "";
|
|
84
|
-
if (array.length === 1)
|
|
85
|
-
return array[0];
|
|
86
|
-
if (array.length === 2)
|
|
87
|
-
return array.join(finalGlue);
|
|
88
|
-
return `${array.slice(0, -1).join(glue)}${finalGlue}${array.slice(-1)}`;
|
|
89
|
-
}
|
|
90
47
|
|
|
91
48
|
const gitCommitTypes = [
|
|
92
49
|
{ value: "init", title: "init: \u9879\u76EE\u521D\u59CB\u5316" },
|
|
@@ -145,11 +102,9 @@ async function gitCommit() {
|
|
|
145
102
|
}
|
|
146
103
|
|
|
147
104
|
function gitCommitVerify() {
|
|
148
|
-
const gitMsgPath =
|
|
105
|
+
const gitMsgPath = `${process.cwd()}/.git/COMMIT_EDITMSG`;
|
|
149
106
|
const commitMsg = actualFS.readFileSync(gitMsgPath, "utf-8").trim();
|
|
150
|
-
const
|
|
151
|
-
const scopes = gitCommitScopes.map((item) => item.value).join("|");
|
|
152
|
-
const REG_EXP = new RegExp(`(${types})!*(\\((${scopes})\\))*!*:\\s.{1,100}`);
|
|
107
|
+
const REG_EXP = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
|
153
108
|
if (!REG_EXP.test(commitMsg)) {
|
|
154
109
|
throw new Error(
|
|
155
110
|
`${kolorist.bgRed(" ERROR ")} ${kolorist.red("Git\u63D0\u4EA4\u4FE1\u606F\u4E0D\u7B26\u5408 Angular \u89C4\u8303!\n\n")}${kolorist.green(
|
|
@@ -7479,10 +7434,10 @@ async function initSimpleGitHooks() {
|
|
|
7479
7434
|
const huskyDir = `${process.cwd()}/.husky`;
|
|
7480
7435
|
const existHusky = actualFS.existsSync(huskyDir);
|
|
7481
7436
|
if (existHusky) {
|
|
7482
|
-
await rimraf.rimraf(
|
|
7437
|
+
await rimraf.rimraf(huskyDir);
|
|
7483
7438
|
await execCommand("git", ["config", "core.hooksPath", ".git/hooks/"], { stdio: "inherit" });
|
|
7484
7439
|
}
|
|
7485
|
-
await rimraf.rimraf(
|
|
7440
|
+
await rimraf.rimraf(`${process.cwd()}/.git/hooks`);
|
|
7486
7441
|
await execCommand("npx", ["simple-git-hooks"], { stdio: "inherit" });
|
|
7487
7442
|
}
|
|
7488
7443
|
|
|
@@ -7525,510 +7480,12 @@ function lintStaged() {
|
|
|
7525
7480
|
execCommand("npx", ["lint-staged", "--config", "@soybeanjs/cli/lint-staged"], { stdio: "inherit" });
|
|
7526
7481
|
}
|
|
7527
7482
|
|
|
7528
|
-
|
|
7529
|
-
const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g;
|
|
7530
|
-
|
|
7531
|
-
async function getTotalGitTags() {
|
|
7532
|
-
const tagStr = await execCommand("git", ["--no-pager", "tag", "-l", "--sort=creatordate"]);
|
|
7533
|
-
const tags = tagStr.split("\n");
|
|
7534
|
-
return tags;
|
|
7535
|
-
}
|
|
7536
|
-
async function getTagDateMap() {
|
|
7537
|
-
const tagDateStr = await execCommand("git", [
|
|
7538
|
-
"--no-pager",
|
|
7539
|
-
"log",
|
|
7540
|
-
"--tags",
|
|
7541
|
-
"--simplify-by-decoration",
|
|
7542
|
-
"--pretty=format:%ci %d"
|
|
7543
|
-
]);
|
|
7544
|
-
const TAG_MARK = "tag: ";
|
|
7545
|
-
const map = /* @__PURE__ */ new Map();
|
|
7546
|
-
const dates = tagDateStr.split("\n").filter((item) => item.includes(TAG_MARK));
|
|
7547
|
-
dates.forEach((item) => {
|
|
7548
|
-
const [dateStr, tagStr] = item.split(TAG_MARK);
|
|
7549
|
-
const date = dayjs__default(dateStr).format("YYYY-MM-DD");
|
|
7550
|
-
const tag = tagStr.match(VERSION_REG)?.[0];
|
|
7551
|
-
if (tag && date) {
|
|
7552
|
-
map.set(tag.trim(), date);
|
|
7553
|
-
}
|
|
7554
|
-
});
|
|
7555
|
-
return map;
|
|
7556
|
-
}
|
|
7557
|
-
function getFromToTags(tags) {
|
|
7558
|
-
const result = [];
|
|
7559
|
-
tags.forEach((tag, index) => {
|
|
7560
|
-
if (index < tags.length - 1) {
|
|
7561
|
-
result.push({ from: tag, to: tags[index + 1] });
|
|
7562
|
-
}
|
|
7563
|
-
});
|
|
7564
|
-
return result;
|
|
7565
|
-
}
|
|
7566
|
-
async function getLastGitTag(delta = 0) {
|
|
7567
|
-
const tags = await getTotalGitTags();
|
|
7568
|
-
return tags[tags.length + delta - 1];
|
|
7569
|
-
}
|
|
7570
|
-
async function getGitMainBranchName() {
|
|
7571
|
-
const main = await execCommand("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
7572
|
-
return main;
|
|
7573
|
-
}
|
|
7574
|
-
async function getCurrentGitBranch() {
|
|
7575
|
-
const tag = await execCommand("git", ["tag", "--points-at", "HEAD"]);
|
|
7576
|
-
const main = getGitMainBranchName();
|
|
7577
|
-
return tag || main;
|
|
7578
|
-
}
|
|
7579
|
-
async function getGitHubRepo() {
|
|
7580
|
-
const url = await execCommand("git", ["config", "--get", "remote.origin.url"]);
|
|
7581
|
-
const match = url.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);
|
|
7582
|
-
if (!match) {
|
|
7583
|
-
throw new Error(`Can not parse GitHub repo from url ${url}`);
|
|
7584
|
-
}
|
|
7585
|
-
return `${match[1]}/${match[2]}`;
|
|
7586
|
-
}
|
|
7587
|
-
function isPrerelease(version) {
|
|
7588
|
-
const REG = /^[^.]*[\d.]+$/;
|
|
7589
|
-
return !REG.test(version);
|
|
7590
|
-
}
|
|
7591
|
-
function getFirstGitCommit() {
|
|
7592
|
-
return execCommand("git", ["rev-list", "--max-parents=0", "HEAD"]);
|
|
7593
|
-
}
|
|
7594
|
-
async function getGitDiff(from, to = "HEAD") {
|
|
7595
|
-
const rawGit = await execCommand("git", [
|
|
7596
|
-
"--no-pager",
|
|
7597
|
-
"log",
|
|
7598
|
-
`${from ? `${from}...` : ""}${to}`,
|
|
7599
|
-
'--pretty="----%n%s|%h|%an|%ae%n%b"',
|
|
7600
|
-
"--name-status"
|
|
7601
|
-
]);
|
|
7602
|
-
const rwaGitLines = rawGit.split("----\n").splice(1);
|
|
7603
|
-
const gitCommits = rwaGitLines.map((line) => {
|
|
7604
|
-
const [firstLine, ...body] = line.split("\n");
|
|
7605
|
-
const [message, shortHash, authorName, authorEmail] = firstLine.split("|");
|
|
7606
|
-
const gitCommmit = {
|
|
7607
|
-
message,
|
|
7608
|
-
shortHash,
|
|
7609
|
-
author: { name: authorName, email: authorEmail },
|
|
7610
|
-
body: body.join("\n")
|
|
7611
|
-
};
|
|
7612
|
-
return gitCommmit;
|
|
7613
|
-
});
|
|
7614
|
-
return gitCommits;
|
|
7615
|
-
}
|
|
7616
|
-
function parseGitCommit(commit, scopeMap) {
|
|
7617
|
-
const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
|
7618
|
-
const CoAuthoredByRegex = /co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim;
|
|
7619
|
-
const PullRequestRE = /\([a-z]*(#\d+)\s*\)/gm;
|
|
7620
|
-
const IssueRE = /(#\d+)/gm;
|
|
7621
|
-
const match = commit.message.match(ConventionalCommitRegex);
|
|
7622
|
-
if (!match?.groups) {
|
|
7623
|
-
return null;
|
|
7624
|
-
}
|
|
7625
|
-
const type = match.groups.type;
|
|
7626
|
-
let scope = match.groups.scope || "";
|
|
7627
|
-
scope = scopeMap[scope] || scope;
|
|
7628
|
-
const isBreaking = Boolean(match.groups.breaking);
|
|
7629
|
-
let description = match.groups.description;
|
|
7630
|
-
const references = [];
|
|
7631
|
-
for (const m of description.matchAll(PullRequestRE)) {
|
|
7632
|
-
references.push({ type: "pull-request", value: m[1] });
|
|
7633
|
-
}
|
|
7634
|
-
for (const m of description.matchAll(IssueRE)) {
|
|
7635
|
-
if (!references.some((i) => i.value === m[1])) {
|
|
7636
|
-
references.push({ type: "issue", value: m[1] });
|
|
7637
|
-
}
|
|
7638
|
-
}
|
|
7639
|
-
references.push({ value: commit.shortHash, type: "hash" });
|
|
7640
|
-
description = description.replace(PullRequestRE, "").trim();
|
|
7641
|
-
const authors = [commit.author];
|
|
7642
|
-
const matchs = commit.body.matchAll(CoAuthoredByRegex);
|
|
7643
|
-
for (const $match of matchs) {
|
|
7644
|
-
const { name = "", email = "" } = $match.groups || {};
|
|
7645
|
-
const author = {
|
|
7646
|
-
name: name.trim(),
|
|
7647
|
-
email: email.trim()
|
|
7648
|
-
};
|
|
7649
|
-
authors.push(author);
|
|
7650
|
-
}
|
|
7651
|
-
return {
|
|
7652
|
-
...commit,
|
|
7653
|
-
authors,
|
|
7654
|
-
resolvedAuthors: [],
|
|
7655
|
-
description,
|
|
7656
|
-
type,
|
|
7657
|
-
scope,
|
|
7658
|
-
references,
|
|
7659
|
-
isBreaking
|
|
7660
|
-
};
|
|
7661
|
-
}
|
|
7662
|
-
async function getGitCommits(from, to = "HEAD", scopeMap = {}) {
|
|
7663
|
-
const rwaGitCommits = await getGitDiff(from, to);
|
|
7664
|
-
const commits = rwaGitCommits.map((commit) => parseGitCommit(commit, scopeMap)).filter(notNullish);
|
|
7665
|
-
return commits;
|
|
7666
|
-
}
|
|
7667
|
-
function getHeaders(githubToken) {
|
|
7668
|
-
return {
|
|
7669
|
-
accept: "application/vnd.github.v3+json",
|
|
7670
|
-
authorization: `token ${githubToken}`
|
|
7671
|
-
};
|
|
7672
|
-
}
|
|
7673
|
-
async function getResolvedAuthorLogin(github, commitHashes, email) {
|
|
7674
|
-
let login = "";
|
|
7675
|
-
try {
|
|
7676
|
-
const data = await ofetch.ofetch(`https://ungh.cc/users/find/${email}`);
|
|
7677
|
-
login = data?.user?.username || "";
|
|
7678
|
-
} catch {
|
|
7679
|
-
}
|
|
7680
|
-
if (login) {
|
|
7681
|
-
return login;
|
|
7682
|
-
}
|
|
7683
|
-
const { repo, token } = github;
|
|
7684
|
-
if (!token) {
|
|
7685
|
-
return login;
|
|
7686
|
-
}
|
|
7687
|
-
if (commitHashes.length) {
|
|
7688
|
-
try {
|
|
7689
|
-
const data = await ofetch.ofetch(`https://api.github.com/repos/${repo}/commits/${commitHashes[0]}`, {
|
|
7690
|
-
headers: getHeaders(token)
|
|
7691
|
-
});
|
|
7692
|
-
login = data?.author?.login || "";
|
|
7693
|
-
} catch (e) {
|
|
7694
|
-
}
|
|
7695
|
-
}
|
|
7696
|
-
if (login) {
|
|
7697
|
-
return login;
|
|
7698
|
-
}
|
|
7699
|
-
try {
|
|
7700
|
-
const data = await ofetch.ofetch(`https://api.github.com/search/users?q=${encodeURIComponent(email)}`, {
|
|
7701
|
-
headers: getHeaders(token)
|
|
7702
|
-
});
|
|
7703
|
-
login = data.items[0].login;
|
|
7704
|
-
} catch (e) {
|
|
7705
|
-
}
|
|
7706
|
-
return login;
|
|
7707
|
-
}
|
|
7708
|
-
async function getGitCommitsAndResolvedAuthors(commits, github, resolvedLogins) {
|
|
7709
|
-
const resultCommits = [];
|
|
7710
|
-
const map = /* @__PURE__ */ new Map();
|
|
7711
|
-
for await (const commit of commits) {
|
|
7712
|
-
const resolvedAuthors = [];
|
|
7713
|
-
for await (const [index, author] of Object.entries(commit.authors)) {
|
|
7714
|
-
const { email, name } = author;
|
|
7715
|
-
if (email && name) {
|
|
7716
|
-
const commitHashes = [];
|
|
7717
|
-
if (index === "0") {
|
|
7718
|
-
commitHashes.push(commit.shortHash);
|
|
7719
|
-
}
|
|
7720
|
-
const resolvedAuthor = {
|
|
7721
|
-
name,
|
|
7722
|
-
email,
|
|
7723
|
-
commits: commitHashes,
|
|
7724
|
-
login: ""
|
|
7725
|
-
};
|
|
7726
|
-
if (!resolvedLogins?.has(email)) {
|
|
7727
|
-
const login = await getResolvedAuthorLogin(github, commitHashes, email);
|
|
7728
|
-
resolvedAuthor.login = login;
|
|
7729
|
-
resolvedLogins?.set(email, login);
|
|
7730
|
-
} else {
|
|
7731
|
-
const login = resolvedLogins?.get(email) || "";
|
|
7732
|
-
resolvedAuthor.login = login;
|
|
7733
|
-
}
|
|
7734
|
-
resolvedAuthors.push(resolvedAuthor);
|
|
7735
|
-
if (!map.has(email)) {
|
|
7736
|
-
map.set(email, resolvedAuthor);
|
|
7737
|
-
}
|
|
7738
|
-
}
|
|
7739
|
-
}
|
|
7740
|
-
const resultCommit = { ...commit, resolvedAuthors };
|
|
7741
|
-
resultCommits.push(resultCommit);
|
|
7742
|
-
}
|
|
7743
|
-
return {
|
|
7744
|
-
commits: resultCommits,
|
|
7745
|
-
contributors: Array.from(map.values())
|
|
7746
|
-
};
|
|
7747
|
-
}
|
|
7748
|
-
|
|
7749
|
-
function formatReferences(references, github, type) {
|
|
7750
|
-
const refs = references.filter((i) => {
|
|
7751
|
-
if (type === "issues")
|
|
7752
|
-
return i.type === "issue" || i.type === "pull-request";
|
|
7753
|
-
return i.type === "hash";
|
|
7754
|
-
}).map((ref) => {
|
|
7755
|
-
if (!github)
|
|
7756
|
-
return ref.value;
|
|
7757
|
-
if (ref.type === "pull-request" || ref.type === "issue")
|
|
7758
|
-
return `https://github.com/${github}/issues/${ref.value.slice(1)}`;
|
|
7759
|
-
return `[<samp>(${ref.value.slice(0, 5)})</samp>](https://github.com/${github}/commit/${ref.value})`;
|
|
7760
|
-
});
|
|
7761
|
-
const referencesString = join(refs).trim();
|
|
7762
|
-
if (type === "issues")
|
|
7763
|
-
return referencesString && `in ${referencesString}`;
|
|
7764
|
-
return referencesString;
|
|
7765
|
-
}
|
|
7766
|
-
function formatLine(commit, options) {
|
|
7767
|
-
const prRefs = formatReferences(commit.references, options.github.repo, "issues");
|
|
7768
|
-
const hashRefs = formatReferences(commit.references, options.github.repo, "hash");
|
|
7769
|
-
let authors = join([...new Set(commit.resolvedAuthors.map((i) => i.login ? `@${i.login}` : `**${i.name}**`))]).trim();
|
|
7770
|
-
if (authors) {
|
|
7771
|
-
authors = `by ${authors}`;
|
|
7772
|
-
}
|
|
7773
|
-
let refs = [authors, prRefs, hashRefs].filter((i) => i?.trim()).join(" ");
|
|
7774
|
-
if (refs) {
|
|
7775
|
-
refs = ` - ${refs}`;
|
|
7776
|
-
}
|
|
7777
|
-
const description = options.capitalize ? capitalize(commit.description) : commit.description;
|
|
7778
|
-
return [description, refs].filter((i) => i?.trim()).join(" ");
|
|
7779
|
-
}
|
|
7780
|
-
function formatTitle(name, options) {
|
|
7781
|
-
const emojisRE = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;
|
|
7782
|
-
let formatName = name.trim();
|
|
7783
|
-
if (!options.emoji) {
|
|
7784
|
-
formatName = name.replace(emojisRE, "").trim();
|
|
7785
|
-
}
|
|
7786
|
-
return `### ${formatName}`;
|
|
7787
|
-
}
|
|
7788
|
-
function formatSection(commits, sectionName, options) {
|
|
7789
|
-
if (!commits.length)
|
|
7790
|
-
return [];
|
|
7791
|
-
const lines = ["", formatTitle(sectionName, options), ""];
|
|
7792
|
-
const scopes = groupBy(commits, "scope");
|
|
7793
|
-
let useScopeGroup = options.group;
|
|
7794
|
-
if (!Object.entries(scopes).some(([k, v]) => k && v.length > 1))
|
|
7795
|
-
useScopeGroup = false;
|
|
7796
|
-
Object.keys(scopes).sort().forEach((scope) => {
|
|
7797
|
-
let padding = "";
|
|
7798
|
-
let prefix = "";
|
|
7799
|
-
const scopeText = `**${options.scopeMap[scope] || scope}**`;
|
|
7800
|
-
if (scope && (useScopeGroup === true || useScopeGroup === "multiple" && scopes[scope].length > 1)) {
|
|
7801
|
-
lines.push(`- ${scopeText}:`);
|
|
7802
|
-
padding = " ";
|
|
7803
|
-
} else if (scope) {
|
|
7804
|
-
prefix = `${scopeText}: `;
|
|
7805
|
-
}
|
|
7806
|
-
lines.push(...scopes[scope].reverse().map((commit) => `${padding}- ${prefix}${formatLine(commit, options)}`));
|
|
7807
|
-
});
|
|
7808
|
-
return lines;
|
|
7809
|
-
}
|
|
7810
|
-
function getUserGithub(userName) {
|
|
7811
|
-
const githubUrl = `https://github.com/${userName}`;
|
|
7812
|
-
return githubUrl;
|
|
7813
|
-
}
|
|
7814
|
-
function getGitUserAvatar(userName) {
|
|
7815
|
-
const githubUrl = getUserGithub(userName);
|
|
7816
|
-
const avatarUrl = `${githubUrl}.png?size=48`;
|
|
7817
|
-
return avatarUrl;
|
|
7818
|
-
}
|
|
7819
|
-
function createContributorLine(contributors) {
|
|
7820
|
-
let loginLine = "";
|
|
7821
|
-
let unloginLine = "";
|
|
7822
|
-
contributors.forEach((contributor, index) => {
|
|
7823
|
-
const { name, email, login } = contributor;
|
|
7824
|
-
if (!login) {
|
|
7825
|
-
let line = `[${name}](mailto:${email})`;
|
|
7826
|
-
if (index < contributors.length - 1) {
|
|
7827
|
-
line += ", ";
|
|
7828
|
-
}
|
|
7829
|
-
unloginLine += line;
|
|
7830
|
-
} else {
|
|
7831
|
-
const githubUrl = getUserGithub(login);
|
|
7832
|
-
const avatar = getGitUserAvatar(login);
|
|
7833
|
-
loginLine += `[](${githubUrl}) `;
|
|
7834
|
-
}
|
|
7835
|
-
});
|
|
7836
|
-
return `${loginLine}
|
|
7837
|
-
${unloginLine}`;
|
|
7838
|
-
}
|
|
7839
|
-
function generateMarkdown(params) {
|
|
7840
|
-
const { commits, options, showTitle, contributors } = params;
|
|
7841
|
-
const lines = [];
|
|
7842
|
-
const url = `https://github.com/${options.github.repo}/compare/${options.from}...${options.to}`;
|
|
7843
|
-
if (showTitle) {
|
|
7844
|
-
const isNewVersion = !VERSION_REG.test(options.to);
|
|
7845
|
-
const version = isNewVersion ? options.newVersion : options.to;
|
|
7846
|
-
const date = isNewVersion ? dayjs__default().format("YY-MM-DD") : options.tagDateMap.get(options.to);
|
|
7847
|
-
let title = `## [${version}](${url})`;
|
|
7848
|
-
if (date) {
|
|
7849
|
-
title += ` (${date})`;
|
|
7850
|
-
}
|
|
7851
|
-
lines.push(title);
|
|
7852
|
-
}
|
|
7853
|
-
const [breaking, changes] = partition(commits, (c) => c.isBreaking);
|
|
7854
|
-
const group = groupBy(changes, "type");
|
|
7855
|
-
lines.push(...formatSection(breaking, options.titles.breakingChanges, options));
|
|
7856
|
-
for (const type of Object.keys(options.types)) {
|
|
7857
|
-
const items = group[type] || [];
|
|
7858
|
-
lines.push(...formatSection(items, options.types[type].title, options));
|
|
7859
|
-
}
|
|
7860
|
-
if (!lines.length) {
|
|
7861
|
-
lines.push("*No significant changes*");
|
|
7862
|
-
}
|
|
7863
|
-
if (!showTitle) {
|
|
7864
|
-
lines.push("", `##### [View changes on GitHub](${url})`);
|
|
7865
|
-
}
|
|
7866
|
-
if (showTitle) {
|
|
7867
|
-
lines.push("", "### \u2764\uFE0F Contributors", "");
|
|
7868
|
-
const contributorLine = createContributorLine(contributors);
|
|
7869
|
-
lines.push(contributorLine);
|
|
7870
|
-
}
|
|
7871
|
-
const md = convertGitmoji.convert(lines.join("\n").trim(), true);
|
|
7872
|
-
return md;
|
|
7873
|
-
}
|
|
7874
|
-
async function isVersionInMarkdown(version, mdPath) {
|
|
7875
|
-
let isIn = false;
|
|
7876
|
-
const md = await promises.readFile(mdPath, "utf8");
|
|
7877
|
-
if (md) {
|
|
7878
|
-
const matches = md.match(VERSION_REG_OF_MARKDOWN);
|
|
7879
|
-
if (matches?.length) {
|
|
7880
|
-
const versionInMarkdown = `## [${version}]`;
|
|
7881
|
-
isIn = matches.includes(versionInMarkdown);
|
|
7882
|
-
}
|
|
7883
|
-
}
|
|
7884
|
-
return isIn;
|
|
7885
|
-
}
|
|
7886
|
-
async function writeMarkdown(md, mdPath, override = false) {
|
|
7887
|
-
let changelogMD;
|
|
7888
|
-
const changelogPrefix = "# Changelog";
|
|
7889
|
-
if (!override && actualFS.existsSync(mdPath)) {
|
|
7890
|
-
changelogMD = await promises.readFile(mdPath, "utf8");
|
|
7891
|
-
if (!changelogMD.startsWith(changelogPrefix)) {
|
|
7892
|
-
changelogMD = `${changelogPrefix}
|
|
7893
|
-
|
|
7894
|
-
${changelogMD}`;
|
|
7895
|
-
}
|
|
7896
|
-
} else {
|
|
7897
|
-
changelogMD = `${changelogPrefix}
|
|
7898
|
-
|
|
7899
|
-
`;
|
|
7900
|
-
}
|
|
7901
|
-
const lastEntry = changelogMD.match(/^###?\s+.*$/m);
|
|
7902
|
-
if (lastEntry) {
|
|
7903
|
-
changelogMD = `${changelogMD.slice(0, lastEntry.index) + md}
|
|
7904
|
-
|
|
7905
|
-
${changelogMD.slice(lastEntry.index)}`;
|
|
7906
|
-
} else {
|
|
7907
|
-
changelogMD += `
|
|
7908
|
-
${md}
|
|
7909
|
-
|
|
7910
|
-
`;
|
|
7911
|
-
}
|
|
7912
|
-
await promises.writeFile(mdPath, changelogMD);
|
|
7913
|
-
}
|
|
7914
|
-
|
|
7915
|
-
function createDefaultOptions() {
|
|
7916
|
-
const cwd = process.cwd();
|
|
7917
|
-
const options = {
|
|
7918
|
-
cwd,
|
|
7919
|
-
types: {
|
|
7920
|
-
feat: { title: "\u{1F680} Features" },
|
|
7921
|
-
fix: { title: "\u{1F41E} Bug Fixes" },
|
|
7922
|
-
perf: { title: "\u{1F525} Performance" },
|
|
7923
|
-
refactor: { title: "\u{1F485} Refactors" },
|
|
7924
|
-
docs: { title: "\u{1F4D6} Documentation" },
|
|
7925
|
-
build: { title: "\u{1F4E6} Build" },
|
|
7926
|
-
types: { title: "\u{1F30A} Types" },
|
|
7927
|
-
chore: { title: "\u{1F3E1} Chore" },
|
|
7928
|
-
examples: { title: "\u{1F3C0} Examples" },
|
|
7929
|
-
test: { title: "\u2705 Tests" },
|
|
7930
|
-
style: { title: "\u{1F3A8} Styles" },
|
|
7931
|
-
ci: { title: "\u{1F916} CI" }
|
|
7932
|
-
},
|
|
7933
|
-
scopeMap: {},
|
|
7934
|
-
github: {
|
|
7935
|
-
repo: "",
|
|
7936
|
-
token: process.env.GITHUB_TOKEN || ""
|
|
7937
|
-
},
|
|
7938
|
-
from: "",
|
|
7939
|
-
to: "",
|
|
7940
|
-
tags: [],
|
|
7941
|
-
tagDateMap: /* @__PURE__ */ new Map(),
|
|
7942
|
-
prerelease: false,
|
|
7943
|
-
capitalize: true,
|
|
7944
|
-
emoji: true,
|
|
7945
|
-
titles: {
|
|
7946
|
-
breakingChanges: "\u{1F6A8} Breaking Changes"
|
|
7947
|
-
},
|
|
7948
|
-
output: "CHANGELOG.md",
|
|
7949
|
-
overrideChangelog: false,
|
|
7950
|
-
newVersion: ""
|
|
7951
|
-
};
|
|
7952
|
-
return options;
|
|
7953
|
-
}
|
|
7954
|
-
async function getOptionsFromPkg(cwd) {
|
|
7955
|
-
let githubToken = "";
|
|
7956
|
-
let newVersion = "";
|
|
7957
|
-
try {
|
|
7958
|
-
const pkgJson = await promises.readFile(`${cwd}/package.json`, "utf-8");
|
|
7959
|
-
const pkg = JSON.parse(pkgJson);
|
|
7960
|
-
githubToken = pkg?.["github-token"] || "";
|
|
7961
|
-
newVersion = pkg?.version || "";
|
|
7962
|
-
} catch {
|
|
7963
|
-
}
|
|
7964
|
-
return {
|
|
7965
|
-
githubToken,
|
|
7966
|
-
newVersion
|
|
7967
|
-
};
|
|
7968
|
-
}
|
|
7969
|
-
async function initOptions() {
|
|
7970
|
-
var _a;
|
|
7971
|
-
const options = createDefaultOptions();
|
|
7972
|
-
const { githubToken, newVersion } = await getOptionsFromPkg(options.cwd);
|
|
7973
|
-
(_a = options.github).token || (_a.token = githubToken);
|
|
7974
|
-
options.github.repo = await getGitHubRepo();
|
|
7975
|
-
options.newVersion || (options.newVersion = `v${newVersion}`);
|
|
7976
|
-
options.from || (options.from = await getLastGitTag());
|
|
7977
|
-
options.to || (options.to = await getCurrentGitBranch());
|
|
7978
|
-
if (options.to === options.from) {
|
|
7979
|
-
const lastTag = await getLastGitTag(-1);
|
|
7980
|
-
const firstCommit = await getFirstGitCommit();
|
|
7981
|
-
options.from = lastTag || firstCommit;
|
|
7982
|
-
}
|
|
7983
|
-
options.tags = await getTotalGitTags();
|
|
7984
|
-
options.tagDateMap = await getTagDateMap();
|
|
7985
|
-
options.prerelease = isPrerelease(options.to);
|
|
7986
|
-
return options;
|
|
7987
|
-
}
|
|
7988
|
-
async function generateChangelogByTag(options) {
|
|
7989
|
-
const gitCommits = await getGitCommits(options.from, options.to, options.scopeMap);
|
|
7990
|
-
const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, options.github);
|
|
7991
|
-
const md = generateMarkdown({ commits, options, showTitle: true, contributors });
|
|
7992
|
-
return md;
|
|
7993
|
-
}
|
|
7994
|
-
async function generateChangelogByTags(options) {
|
|
7995
|
-
const tags = getFromToTags(options.tags);
|
|
7996
|
-
const bar = new cliProgress__default.SingleBar({}, cliProgress__default.Presets.shades_classic);
|
|
7997
|
-
bar.start(tags.length, 0);
|
|
7998
|
-
let md = "";
|
|
7999
|
-
const resolvedLogins = /* @__PURE__ */ new Map();
|
|
8000
|
-
for await (const [index, tag] of tags.entries()) {
|
|
8001
|
-
const { from, to } = tag;
|
|
8002
|
-
const gitCommits = await getGitCommits(from, to, options.scopeMap);
|
|
8003
|
-
const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, options.github, resolvedLogins);
|
|
8004
|
-
const opts = { ...options, from, to };
|
|
8005
|
-
const nextMd = generateMarkdown({ commits, options: opts, showTitle: true, contributors });
|
|
8006
|
-
md = `${nextMd}
|
|
8007
|
-
|
|
8008
|
-
${md}`;
|
|
8009
|
-
bar.update(index + 1);
|
|
8010
|
-
}
|
|
8011
|
-
bar.stop();
|
|
8012
|
-
return md;
|
|
8013
|
-
}
|
|
8014
|
-
async function generateChangelog(total = false) {
|
|
8015
|
-
const options = await initOptions();
|
|
8016
|
-
let md = "";
|
|
7483
|
+
function genChangelog(total = false) {
|
|
8017
7484
|
if (total) {
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
}
|
|
8022
|
-
const isIn = await isVersionInMarkdown(options.to, options.output);
|
|
8023
|
-
if (!options.overrideChangelog && isIn) {
|
|
8024
|
-
return;
|
|
7485
|
+
changelog.generateTotalChangelog();
|
|
7486
|
+
} else {
|
|
7487
|
+
changelog.generateChangelog();
|
|
8025
7488
|
}
|
|
8026
|
-
md = await generateChangelogByTag(options);
|
|
8027
|
-
await writeMarkdown(md, options.output, false);
|
|
8028
|
-
}
|
|
8029
|
-
|
|
8030
|
-
async function genChangelog(total = false) {
|
|
8031
|
-
await generateChangelog(total);
|
|
8032
7489
|
}
|
|
8033
7490
|
|
|
8034
7491
|
async function release() {
|
|
@@ -8092,3 +7549,8 @@ Object.entries(commands).forEach(([command, { desc, action }]) => {
|
|
|
8092
7549
|
cli.command(command, desc).action(action);
|
|
8093
7550
|
});
|
|
8094
7551
|
cli.parse();
|
|
7552
|
+
function defineConfig(config) {
|
|
7553
|
+
return config;
|
|
7554
|
+
}
|
|
7555
|
+
|
|
7556
|
+
exports.defineConfig = defineConfig;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ChangelogOption } from '@soybeanjs/changelog';
|
|
2
|
+
|
|
3
|
+
interface CliOption {
|
|
4
|
+
name?: string;
|
|
5
|
+
/**
|
|
6
|
+
* options of generate changelog
|
|
7
|
+
* @link https://github.com/soybeanjs/changelog
|
|
8
|
+
*/
|
|
9
|
+
changelogOptions?: Partial<ChangelogOption>;
|
|
10
|
+
prettierFormatFiles?: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare function defineConfig(config?: Partial<CliOption>): Partial<CliOption> | undefined;
|
|
14
|
+
|
|
15
|
+
export { CliOption, defineConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -7,61 +7,20 @@ import { bgRed, red, green } from 'kolorist';
|
|
|
7
7
|
import { rimraf } from 'rimraf';
|
|
8
8
|
import { win32, posix } from 'path';
|
|
9
9
|
import { fileURLToPath } from 'url';
|
|
10
|
-
import { lstat, readdir as readdir$1, readlink, realpath
|
|
10
|
+
import { lstat, readdir as readdir$1, readlink, realpath } from 'fs/promises';
|
|
11
11
|
import EE from 'events';
|
|
12
12
|
import Stream from 'stream';
|
|
13
13
|
import stringdecoder from 'string_decoder';
|
|
14
|
-
import
|
|
15
|
-
import { ofetch } from 'ofetch';
|
|
16
|
-
import dayjs from 'dayjs';
|
|
17
|
-
import { convert } from 'convert-gitmoji';
|
|
14
|
+
import { generateTotalChangelog, generateChangelog } from '@soybeanjs/changelog';
|
|
18
15
|
import versionBumpp from 'bumpp';
|
|
19
16
|
|
|
20
|
-
const version = "0.5.
|
|
17
|
+
const version = "0.5.3";
|
|
21
18
|
|
|
22
19
|
async function execCommand(cmd, args, options) {
|
|
23
20
|
const { execa } = await import('execa');
|
|
24
21
|
const res = await execa(cmd, args, options);
|
|
25
22
|
return res?.stdout?.trim() || "";
|
|
26
23
|
}
|
|
27
|
-
function notNullish(v) {
|
|
28
|
-
return v !== null && v !== void 0;
|
|
29
|
-
}
|
|
30
|
-
function partition(array, ...filters) {
|
|
31
|
-
const result = new Array(filters.length + 1).fill(null).map(() => []);
|
|
32
|
-
array.forEach((e, idx, arr) => {
|
|
33
|
-
let i = 0;
|
|
34
|
-
for (const filter of filters) {
|
|
35
|
-
if (filter(e, idx, arr)) {
|
|
36
|
-
result[i].push(e);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
i += 1;
|
|
40
|
-
}
|
|
41
|
-
result[i].push(e);
|
|
42
|
-
});
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
function groupBy(items, key, groups = {}) {
|
|
46
|
-
for (const item of items) {
|
|
47
|
-
const v = item[key];
|
|
48
|
-
groups[v] = groups[v] || [];
|
|
49
|
-
groups[v].push(item);
|
|
50
|
-
}
|
|
51
|
-
return groups;
|
|
52
|
-
}
|
|
53
|
-
function capitalize(str) {
|
|
54
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
55
|
-
}
|
|
56
|
-
function join(array, glue = ", ", finalGlue = " and ") {
|
|
57
|
-
if (!array || array.length === 0)
|
|
58
|
-
return "";
|
|
59
|
-
if (array.length === 1)
|
|
60
|
-
return array[0];
|
|
61
|
-
if (array.length === 2)
|
|
62
|
-
return array.join(finalGlue);
|
|
63
|
-
return `${array.slice(0, -1).join(glue)}${finalGlue}${array.slice(-1)}`;
|
|
64
|
-
}
|
|
65
24
|
|
|
66
25
|
const gitCommitTypes = [
|
|
67
26
|
{ value: "init", title: "init: \u9879\u76EE\u521D\u59CB\u5316" },
|
|
@@ -120,11 +79,9 @@ async function gitCommit() {
|
|
|
120
79
|
}
|
|
121
80
|
|
|
122
81
|
function gitCommitVerify() {
|
|
123
|
-
const gitMsgPath =
|
|
82
|
+
const gitMsgPath = `${process.cwd()}/.git/COMMIT_EDITMSG`;
|
|
124
83
|
const commitMsg = readFileSync(gitMsgPath, "utf-8").trim();
|
|
125
|
-
const
|
|
126
|
-
const scopes = gitCommitScopes.map((item) => item.value).join("|");
|
|
127
|
-
const REG_EXP = new RegExp(`(${types})!*(\\((${scopes})\\))*!*:\\s.{1,100}`);
|
|
84
|
+
const REG_EXP = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
|
128
85
|
if (!REG_EXP.test(commitMsg)) {
|
|
129
86
|
throw new Error(
|
|
130
87
|
`${bgRed(" ERROR ")} ${red("Git\u63D0\u4EA4\u4FE1\u606F\u4E0D\u7B26\u5408 Angular \u89C4\u8303!\n\n")}${green(
|
|
@@ -7454,10 +7411,10 @@ async function initSimpleGitHooks() {
|
|
|
7454
7411
|
const huskyDir = `${process.cwd()}/.husky`;
|
|
7455
7412
|
const existHusky = existsSync(huskyDir);
|
|
7456
7413
|
if (existHusky) {
|
|
7457
|
-
await rimraf(
|
|
7414
|
+
await rimraf(huskyDir);
|
|
7458
7415
|
await execCommand("git", ["config", "core.hooksPath", ".git/hooks/"], { stdio: "inherit" });
|
|
7459
7416
|
}
|
|
7460
|
-
await rimraf(
|
|
7417
|
+
await rimraf(`${process.cwd()}/.git/hooks`);
|
|
7461
7418
|
await execCommand("npx", ["simple-git-hooks"], { stdio: "inherit" });
|
|
7462
7419
|
}
|
|
7463
7420
|
|
|
@@ -7500,510 +7457,12 @@ function lintStaged() {
|
|
|
7500
7457
|
execCommand("npx", ["lint-staged", "--config", "@soybeanjs/cli/lint-staged"], { stdio: "inherit" });
|
|
7501
7458
|
}
|
|
7502
7459
|
|
|
7503
|
-
|
|
7504
|
-
const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g;
|
|
7505
|
-
|
|
7506
|
-
async function getTotalGitTags() {
|
|
7507
|
-
const tagStr = await execCommand("git", ["--no-pager", "tag", "-l", "--sort=creatordate"]);
|
|
7508
|
-
const tags = tagStr.split("\n");
|
|
7509
|
-
return tags;
|
|
7510
|
-
}
|
|
7511
|
-
async function getTagDateMap() {
|
|
7512
|
-
const tagDateStr = await execCommand("git", [
|
|
7513
|
-
"--no-pager",
|
|
7514
|
-
"log",
|
|
7515
|
-
"--tags",
|
|
7516
|
-
"--simplify-by-decoration",
|
|
7517
|
-
"--pretty=format:%ci %d"
|
|
7518
|
-
]);
|
|
7519
|
-
const TAG_MARK = "tag: ";
|
|
7520
|
-
const map = /* @__PURE__ */ new Map();
|
|
7521
|
-
const dates = tagDateStr.split("\n").filter((item) => item.includes(TAG_MARK));
|
|
7522
|
-
dates.forEach((item) => {
|
|
7523
|
-
const [dateStr, tagStr] = item.split(TAG_MARK);
|
|
7524
|
-
const date = dayjs(dateStr).format("YYYY-MM-DD");
|
|
7525
|
-
const tag = tagStr.match(VERSION_REG)?.[0];
|
|
7526
|
-
if (tag && date) {
|
|
7527
|
-
map.set(tag.trim(), date);
|
|
7528
|
-
}
|
|
7529
|
-
});
|
|
7530
|
-
return map;
|
|
7531
|
-
}
|
|
7532
|
-
function getFromToTags(tags) {
|
|
7533
|
-
const result = [];
|
|
7534
|
-
tags.forEach((tag, index) => {
|
|
7535
|
-
if (index < tags.length - 1) {
|
|
7536
|
-
result.push({ from: tag, to: tags[index + 1] });
|
|
7537
|
-
}
|
|
7538
|
-
});
|
|
7539
|
-
return result;
|
|
7540
|
-
}
|
|
7541
|
-
async function getLastGitTag(delta = 0) {
|
|
7542
|
-
const tags = await getTotalGitTags();
|
|
7543
|
-
return tags[tags.length + delta - 1];
|
|
7544
|
-
}
|
|
7545
|
-
async function getGitMainBranchName() {
|
|
7546
|
-
const main = await execCommand("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
7547
|
-
return main;
|
|
7548
|
-
}
|
|
7549
|
-
async function getCurrentGitBranch() {
|
|
7550
|
-
const tag = await execCommand("git", ["tag", "--points-at", "HEAD"]);
|
|
7551
|
-
const main = getGitMainBranchName();
|
|
7552
|
-
return tag || main;
|
|
7553
|
-
}
|
|
7554
|
-
async function getGitHubRepo() {
|
|
7555
|
-
const url = await execCommand("git", ["config", "--get", "remote.origin.url"]);
|
|
7556
|
-
const match = url.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);
|
|
7557
|
-
if (!match) {
|
|
7558
|
-
throw new Error(`Can not parse GitHub repo from url ${url}`);
|
|
7559
|
-
}
|
|
7560
|
-
return `${match[1]}/${match[2]}`;
|
|
7561
|
-
}
|
|
7562
|
-
function isPrerelease(version) {
|
|
7563
|
-
const REG = /^[^.]*[\d.]+$/;
|
|
7564
|
-
return !REG.test(version);
|
|
7565
|
-
}
|
|
7566
|
-
function getFirstGitCommit() {
|
|
7567
|
-
return execCommand("git", ["rev-list", "--max-parents=0", "HEAD"]);
|
|
7568
|
-
}
|
|
7569
|
-
async function getGitDiff(from, to = "HEAD") {
|
|
7570
|
-
const rawGit = await execCommand("git", [
|
|
7571
|
-
"--no-pager",
|
|
7572
|
-
"log",
|
|
7573
|
-
`${from ? `${from}...` : ""}${to}`,
|
|
7574
|
-
'--pretty="----%n%s|%h|%an|%ae%n%b"',
|
|
7575
|
-
"--name-status"
|
|
7576
|
-
]);
|
|
7577
|
-
const rwaGitLines = rawGit.split("----\n").splice(1);
|
|
7578
|
-
const gitCommits = rwaGitLines.map((line) => {
|
|
7579
|
-
const [firstLine, ...body] = line.split("\n");
|
|
7580
|
-
const [message, shortHash, authorName, authorEmail] = firstLine.split("|");
|
|
7581
|
-
const gitCommmit = {
|
|
7582
|
-
message,
|
|
7583
|
-
shortHash,
|
|
7584
|
-
author: { name: authorName, email: authorEmail },
|
|
7585
|
-
body: body.join("\n")
|
|
7586
|
-
};
|
|
7587
|
-
return gitCommmit;
|
|
7588
|
-
});
|
|
7589
|
-
return gitCommits;
|
|
7590
|
-
}
|
|
7591
|
-
function parseGitCommit(commit, scopeMap) {
|
|
7592
|
-
const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
|
7593
|
-
const CoAuthoredByRegex = /co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim;
|
|
7594
|
-
const PullRequestRE = /\([a-z]*(#\d+)\s*\)/gm;
|
|
7595
|
-
const IssueRE = /(#\d+)/gm;
|
|
7596
|
-
const match = commit.message.match(ConventionalCommitRegex);
|
|
7597
|
-
if (!match?.groups) {
|
|
7598
|
-
return null;
|
|
7599
|
-
}
|
|
7600
|
-
const type = match.groups.type;
|
|
7601
|
-
let scope = match.groups.scope || "";
|
|
7602
|
-
scope = scopeMap[scope] || scope;
|
|
7603
|
-
const isBreaking = Boolean(match.groups.breaking);
|
|
7604
|
-
let description = match.groups.description;
|
|
7605
|
-
const references = [];
|
|
7606
|
-
for (const m of description.matchAll(PullRequestRE)) {
|
|
7607
|
-
references.push({ type: "pull-request", value: m[1] });
|
|
7608
|
-
}
|
|
7609
|
-
for (const m of description.matchAll(IssueRE)) {
|
|
7610
|
-
if (!references.some((i) => i.value === m[1])) {
|
|
7611
|
-
references.push({ type: "issue", value: m[1] });
|
|
7612
|
-
}
|
|
7613
|
-
}
|
|
7614
|
-
references.push({ value: commit.shortHash, type: "hash" });
|
|
7615
|
-
description = description.replace(PullRequestRE, "").trim();
|
|
7616
|
-
const authors = [commit.author];
|
|
7617
|
-
const matchs = commit.body.matchAll(CoAuthoredByRegex);
|
|
7618
|
-
for (const $match of matchs) {
|
|
7619
|
-
const { name = "", email = "" } = $match.groups || {};
|
|
7620
|
-
const author = {
|
|
7621
|
-
name: name.trim(),
|
|
7622
|
-
email: email.trim()
|
|
7623
|
-
};
|
|
7624
|
-
authors.push(author);
|
|
7625
|
-
}
|
|
7626
|
-
return {
|
|
7627
|
-
...commit,
|
|
7628
|
-
authors,
|
|
7629
|
-
resolvedAuthors: [],
|
|
7630
|
-
description,
|
|
7631
|
-
type,
|
|
7632
|
-
scope,
|
|
7633
|
-
references,
|
|
7634
|
-
isBreaking
|
|
7635
|
-
};
|
|
7636
|
-
}
|
|
7637
|
-
async function getGitCommits(from, to = "HEAD", scopeMap = {}) {
|
|
7638
|
-
const rwaGitCommits = await getGitDiff(from, to);
|
|
7639
|
-
const commits = rwaGitCommits.map((commit) => parseGitCommit(commit, scopeMap)).filter(notNullish);
|
|
7640
|
-
return commits;
|
|
7641
|
-
}
|
|
7642
|
-
function getHeaders(githubToken) {
|
|
7643
|
-
return {
|
|
7644
|
-
accept: "application/vnd.github.v3+json",
|
|
7645
|
-
authorization: `token ${githubToken}`
|
|
7646
|
-
};
|
|
7647
|
-
}
|
|
7648
|
-
async function getResolvedAuthorLogin(github, commitHashes, email) {
|
|
7649
|
-
let login = "";
|
|
7650
|
-
try {
|
|
7651
|
-
const data = await ofetch(`https://ungh.cc/users/find/${email}`);
|
|
7652
|
-
login = data?.user?.username || "";
|
|
7653
|
-
} catch {
|
|
7654
|
-
}
|
|
7655
|
-
if (login) {
|
|
7656
|
-
return login;
|
|
7657
|
-
}
|
|
7658
|
-
const { repo, token } = github;
|
|
7659
|
-
if (!token) {
|
|
7660
|
-
return login;
|
|
7661
|
-
}
|
|
7662
|
-
if (commitHashes.length) {
|
|
7663
|
-
try {
|
|
7664
|
-
const data = await ofetch(`https://api.github.com/repos/${repo}/commits/${commitHashes[0]}`, {
|
|
7665
|
-
headers: getHeaders(token)
|
|
7666
|
-
});
|
|
7667
|
-
login = data?.author?.login || "";
|
|
7668
|
-
} catch (e) {
|
|
7669
|
-
}
|
|
7670
|
-
}
|
|
7671
|
-
if (login) {
|
|
7672
|
-
return login;
|
|
7673
|
-
}
|
|
7674
|
-
try {
|
|
7675
|
-
const data = await ofetch(`https://api.github.com/search/users?q=${encodeURIComponent(email)}`, {
|
|
7676
|
-
headers: getHeaders(token)
|
|
7677
|
-
});
|
|
7678
|
-
login = data.items[0].login;
|
|
7679
|
-
} catch (e) {
|
|
7680
|
-
}
|
|
7681
|
-
return login;
|
|
7682
|
-
}
|
|
7683
|
-
async function getGitCommitsAndResolvedAuthors(commits, github, resolvedLogins) {
|
|
7684
|
-
const resultCommits = [];
|
|
7685
|
-
const map = /* @__PURE__ */ new Map();
|
|
7686
|
-
for await (const commit of commits) {
|
|
7687
|
-
const resolvedAuthors = [];
|
|
7688
|
-
for await (const [index, author] of Object.entries(commit.authors)) {
|
|
7689
|
-
const { email, name } = author;
|
|
7690
|
-
if (email && name) {
|
|
7691
|
-
const commitHashes = [];
|
|
7692
|
-
if (index === "0") {
|
|
7693
|
-
commitHashes.push(commit.shortHash);
|
|
7694
|
-
}
|
|
7695
|
-
const resolvedAuthor = {
|
|
7696
|
-
name,
|
|
7697
|
-
email,
|
|
7698
|
-
commits: commitHashes,
|
|
7699
|
-
login: ""
|
|
7700
|
-
};
|
|
7701
|
-
if (!resolvedLogins?.has(email)) {
|
|
7702
|
-
const login = await getResolvedAuthorLogin(github, commitHashes, email);
|
|
7703
|
-
resolvedAuthor.login = login;
|
|
7704
|
-
resolvedLogins?.set(email, login);
|
|
7705
|
-
} else {
|
|
7706
|
-
const login = resolvedLogins?.get(email) || "";
|
|
7707
|
-
resolvedAuthor.login = login;
|
|
7708
|
-
}
|
|
7709
|
-
resolvedAuthors.push(resolvedAuthor);
|
|
7710
|
-
if (!map.has(email)) {
|
|
7711
|
-
map.set(email, resolvedAuthor);
|
|
7712
|
-
}
|
|
7713
|
-
}
|
|
7714
|
-
}
|
|
7715
|
-
const resultCommit = { ...commit, resolvedAuthors };
|
|
7716
|
-
resultCommits.push(resultCommit);
|
|
7717
|
-
}
|
|
7718
|
-
return {
|
|
7719
|
-
commits: resultCommits,
|
|
7720
|
-
contributors: Array.from(map.values())
|
|
7721
|
-
};
|
|
7722
|
-
}
|
|
7723
|
-
|
|
7724
|
-
function formatReferences(references, github, type) {
|
|
7725
|
-
const refs = references.filter((i) => {
|
|
7726
|
-
if (type === "issues")
|
|
7727
|
-
return i.type === "issue" || i.type === "pull-request";
|
|
7728
|
-
return i.type === "hash";
|
|
7729
|
-
}).map((ref) => {
|
|
7730
|
-
if (!github)
|
|
7731
|
-
return ref.value;
|
|
7732
|
-
if (ref.type === "pull-request" || ref.type === "issue")
|
|
7733
|
-
return `https://github.com/${github}/issues/${ref.value.slice(1)}`;
|
|
7734
|
-
return `[<samp>(${ref.value.slice(0, 5)})</samp>](https://github.com/${github}/commit/${ref.value})`;
|
|
7735
|
-
});
|
|
7736
|
-
const referencesString = join(refs).trim();
|
|
7737
|
-
if (type === "issues")
|
|
7738
|
-
return referencesString && `in ${referencesString}`;
|
|
7739
|
-
return referencesString;
|
|
7740
|
-
}
|
|
7741
|
-
function formatLine(commit, options) {
|
|
7742
|
-
const prRefs = formatReferences(commit.references, options.github.repo, "issues");
|
|
7743
|
-
const hashRefs = formatReferences(commit.references, options.github.repo, "hash");
|
|
7744
|
-
let authors = join([...new Set(commit.resolvedAuthors.map((i) => i.login ? `@${i.login}` : `**${i.name}**`))]).trim();
|
|
7745
|
-
if (authors) {
|
|
7746
|
-
authors = `by ${authors}`;
|
|
7747
|
-
}
|
|
7748
|
-
let refs = [authors, prRefs, hashRefs].filter((i) => i?.trim()).join(" ");
|
|
7749
|
-
if (refs) {
|
|
7750
|
-
refs = ` - ${refs}`;
|
|
7751
|
-
}
|
|
7752
|
-
const description = options.capitalize ? capitalize(commit.description) : commit.description;
|
|
7753
|
-
return [description, refs].filter((i) => i?.trim()).join(" ");
|
|
7754
|
-
}
|
|
7755
|
-
function formatTitle(name, options) {
|
|
7756
|
-
const emojisRE = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;
|
|
7757
|
-
let formatName = name.trim();
|
|
7758
|
-
if (!options.emoji) {
|
|
7759
|
-
formatName = name.replace(emojisRE, "").trim();
|
|
7760
|
-
}
|
|
7761
|
-
return `### ${formatName}`;
|
|
7762
|
-
}
|
|
7763
|
-
function formatSection(commits, sectionName, options) {
|
|
7764
|
-
if (!commits.length)
|
|
7765
|
-
return [];
|
|
7766
|
-
const lines = ["", formatTitle(sectionName, options), ""];
|
|
7767
|
-
const scopes = groupBy(commits, "scope");
|
|
7768
|
-
let useScopeGroup = options.group;
|
|
7769
|
-
if (!Object.entries(scopes).some(([k, v]) => k && v.length > 1))
|
|
7770
|
-
useScopeGroup = false;
|
|
7771
|
-
Object.keys(scopes).sort().forEach((scope) => {
|
|
7772
|
-
let padding = "";
|
|
7773
|
-
let prefix = "";
|
|
7774
|
-
const scopeText = `**${options.scopeMap[scope] || scope}**`;
|
|
7775
|
-
if (scope && (useScopeGroup === true || useScopeGroup === "multiple" && scopes[scope].length > 1)) {
|
|
7776
|
-
lines.push(`- ${scopeText}:`);
|
|
7777
|
-
padding = " ";
|
|
7778
|
-
} else if (scope) {
|
|
7779
|
-
prefix = `${scopeText}: `;
|
|
7780
|
-
}
|
|
7781
|
-
lines.push(...scopes[scope].reverse().map((commit) => `${padding}- ${prefix}${formatLine(commit, options)}`));
|
|
7782
|
-
});
|
|
7783
|
-
return lines;
|
|
7784
|
-
}
|
|
7785
|
-
function getUserGithub(userName) {
|
|
7786
|
-
const githubUrl = `https://github.com/${userName}`;
|
|
7787
|
-
return githubUrl;
|
|
7788
|
-
}
|
|
7789
|
-
function getGitUserAvatar(userName) {
|
|
7790
|
-
const githubUrl = getUserGithub(userName);
|
|
7791
|
-
const avatarUrl = `${githubUrl}.png?size=48`;
|
|
7792
|
-
return avatarUrl;
|
|
7793
|
-
}
|
|
7794
|
-
function createContributorLine(contributors) {
|
|
7795
|
-
let loginLine = "";
|
|
7796
|
-
let unloginLine = "";
|
|
7797
|
-
contributors.forEach((contributor, index) => {
|
|
7798
|
-
const { name, email, login } = contributor;
|
|
7799
|
-
if (!login) {
|
|
7800
|
-
let line = `[${name}](mailto:${email})`;
|
|
7801
|
-
if (index < contributors.length - 1) {
|
|
7802
|
-
line += ", ";
|
|
7803
|
-
}
|
|
7804
|
-
unloginLine += line;
|
|
7805
|
-
} else {
|
|
7806
|
-
const githubUrl = getUserGithub(login);
|
|
7807
|
-
const avatar = getGitUserAvatar(login);
|
|
7808
|
-
loginLine += `[](${githubUrl}) `;
|
|
7809
|
-
}
|
|
7810
|
-
});
|
|
7811
|
-
return `${loginLine}
|
|
7812
|
-
${unloginLine}`;
|
|
7813
|
-
}
|
|
7814
|
-
function generateMarkdown(params) {
|
|
7815
|
-
const { commits, options, showTitle, contributors } = params;
|
|
7816
|
-
const lines = [];
|
|
7817
|
-
const url = `https://github.com/${options.github.repo}/compare/${options.from}...${options.to}`;
|
|
7818
|
-
if (showTitle) {
|
|
7819
|
-
const isNewVersion = !VERSION_REG.test(options.to);
|
|
7820
|
-
const version = isNewVersion ? options.newVersion : options.to;
|
|
7821
|
-
const date = isNewVersion ? dayjs().format("YY-MM-DD") : options.tagDateMap.get(options.to);
|
|
7822
|
-
let title = `## [${version}](${url})`;
|
|
7823
|
-
if (date) {
|
|
7824
|
-
title += ` (${date})`;
|
|
7825
|
-
}
|
|
7826
|
-
lines.push(title);
|
|
7827
|
-
}
|
|
7828
|
-
const [breaking, changes] = partition(commits, (c) => c.isBreaking);
|
|
7829
|
-
const group = groupBy(changes, "type");
|
|
7830
|
-
lines.push(...formatSection(breaking, options.titles.breakingChanges, options));
|
|
7831
|
-
for (const type of Object.keys(options.types)) {
|
|
7832
|
-
const items = group[type] || [];
|
|
7833
|
-
lines.push(...formatSection(items, options.types[type].title, options));
|
|
7834
|
-
}
|
|
7835
|
-
if (!lines.length) {
|
|
7836
|
-
lines.push("*No significant changes*");
|
|
7837
|
-
}
|
|
7838
|
-
if (!showTitle) {
|
|
7839
|
-
lines.push("", `##### [View changes on GitHub](${url})`);
|
|
7840
|
-
}
|
|
7841
|
-
if (showTitle) {
|
|
7842
|
-
lines.push("", "### \u2764\uFE0F Contributors", "");
|
|
7843
|
-
const contributorLine = createContributorLine(contributors);
|
|
7844
|
-
lines.push(contributorLine);
|
|
7845
|
-
}
|
|
7846
|
-
const md = convert(lines.join("\n").trim(), true);
|
|
7847
|
-
return md;
|
|
7848
|
-
}
|
|
7849
|
-
async function isVersionInMarkdown(version, mdPath) {
|
|
7850
|
-
let isIn = false;
|
|
7851
|
-
const md = await readFile(mdPath, "utf8");
|
|
7852
|
-
if (md) {
|
|
7853
|
-
const matches = md.match(VERSION_REG_OF_MARKDOWN);
|
|
7854
|
-
if (matches?.length) {
|
|
7855
|
-
const versionInMarkdown = `## [${version}]`;
|
|
7856
|
-
isIn = matches.includes(versionInMarkdown);
|
|
7857
|
-
}
|
|
7858
|
-
}
|
|
7859
|
-
return isIn;
|
|
7860
|
-
}
|
|
7861
|
-
async function writeMarkdown(md, mdPath, override = false) {
|
|
7862
|
-
let changelogMD;
|
|
7863
|
-
const changelogPrefix = "# Changelog";
|
|
7864
|
-
if (!override && existsSync(mdPath)) {
|
|
7865
|
-
changelogMD = await readFile(mdPath, "utf8");
|
|
7866
|
-
if (!changelogMD.startsWith(changelogPrefix)) {
|
|
7867
|
-
changelogMD = `${changelogPrefix}
|
|
7868
|
-
|
|
7869
|
-
${changelogMD}`;
|
|
7870
|
-
}
|
|
7871
|
-
} else {
|
|
7872
|
-
changelogMD = `${changelogPrefix}
|
|
7873
|
-
|
|
7874
|
-
`;
|
|
7875
|
-
}
|
|
7876
|
-
const lastEntry = changelogMD.match(/^###?\s+.*$/m);
|
|
7877
|
-
if (lastEntry) {
|
|
7878
|
-
changelogMD = `${changelogMD.slice(0, lastEntry.index) + md}
|
|
7879
|
-
|
|
7880
|
-
${changelogMD.slice(lastEntry.index)}`;
|
|
7881
|
-
} else {
|
|
7882
|
-
changelogMD += `
|
|
7883
|
-
${md}
|
|
7884
|
-
|
|
7885
|
-
`;
|
|
7886
|
-
}
|
|
7887
|
-
await writeFile(mdPath, changelogMD);
|
|
7888
|
-
}
|
|
7889
|
-
|
|
7890
|
-
function createDefaultOptions() {
|
|
7891
|
-
const cwd = process.cwd();
|
|
7892
|
-
const options = {
|
|
7893
|
-
cwd,
|
|
7894
|
-
types: {
|
|
7895
|
-
feat: { title: "\u{1F680} Features" },
|
|
7896
|
-
fix: { title: "\u{1F41E} Bug Fixes" },
|
|
7897
|
-
perf: { title: "\u{1F525} Performance" },
|
|
7898
|
-
refactor: { title: "\u{1F485} Refactors" },
|
|
7899
|
-
docs: { title: "\u{1F4D6} Documentation" },
|
|
7900
|
-
build: { title: "\u{1F4E6} Build" },
|
|
7901
|
-
types: { title: "\u{1F30A} Types" },
|
|
7902
|
-
chore: { title: "\u{1F3E1} Chore" },
|
|
7903
|
-
examples: { title: "\u{1F3C0} Examples" },
|
|
7904
|
-
test: { title: "\u2705 Tests" },
|
|
7905
|
-
style: { title: "\u{1F3A8} Styles" },
|
|
7906
|
-
ci: { title: "\u{1F916} CI" }
|
|
7907
|
-
},
|
|
7908
|
-
scopeMap: {},
|
|
7909
|
-
github: {
|
|
7910
|
-
repo: "",
|
|
7911
|
-
token: process.env.GITHUB_TOKEN || ""
|
|
7912
|
-
},
|
|
7913
|
-
from: "",
|
|
7914
|
-
to: "",
|
|
7915
|
-
tags: [],
|
|
7916
|
-
tagDateMap: /* @__PURE__ */ new Map(),
|
|
7917
|
-
prerelease: false,
|
|
7918
|
-
capitalize: true,
|
|
7919
|
-
emoji: true,
|
|
7920
|
-
titles: {
|
|
7921
|
-
breakingChanges: "\u{1F6A8} Breaking Changes"
|
|
7922
|
-
},
|
|
7923
|
-
output: "CHANGELOG.md",
|
|
7924
|
-
overrideChangelog: false,
|
|
7925
|
-
newVersion: ""
|
|
7926
|
-
};
|
|
7927
|
-
return options;
|
|
7928
|
-
}
|
|
7929
|
-
async function getOptionsFromPkg(cwd) {
|
|
7930
|
-
let githubToken = "";
|
|
7931
|
-
let newVersion = "";
|
|
7932
|
-
try {
|
|
7933
|
-
const pkgJson = await readFile(`${cwd}/package.json`, "utf-8");
|
|
7934
|
-
const pkg = JSON.parse(pkgJson);
|
|
7935
|
-
githubToken = pkg?.["github-token"] || "";
|
|
7936
|
-
newVersion = pkg?.version || "";
|
|
7937
|
-
} catch {
|
|
7938
|
-
}
|
|
7939
|
-
return {
|
|
7940
|
-
githubToken,
|
|
7941
|
-
newVersion
|
|
7942
|
-
};
|
|
7943
|
-
}
|
|
7944
|
-
async function initOptions() {
|
|
7945
|
-
var _a;
|
|
7946
|
-
const options = createDefaultOptions();
|
|
7947
|
-
const { githubToken, newVersion } = await getOptionsFromPkg(options.cwd);
|
|
7948
|
-
(_a = options.github).token || (_a.token = githubToken);
|
|
7949
|
-
options.github.repo = await getGitHubRepo();
|
|
7950
|
-
options.newVersion || (options.newVersion = `v${newVersion}`);
|
|
7951
|
-
options.from || (options.from = await getLastGitTag());
|
|
7952
|
-
options.to || (options.to = await getCurrentGitBranch());
|
|
7953
|
-
if (options.to === options.from) {
|
|
7954
|
-
const lastTag = await getLastGitTag(-1);
|
|
7955
|
-
const firstCommit = await getFirstGitCommit();
|
|
7956
|
-
options.from = lastTag || firstCommit;
|
|
7957
|
-
}
|
|
7958
|
-
options.tags = await getTotalGitTags();
|
|
7959
|
-
options.tagDateMap = await getTagDateMap();
|
|
7960
|
-
options.prerelease = isPrerelease(options.to);
|
|
7961
|
-
return options;
|
|
7962
|
-
}
|
|
7963
|
-
async function generateChangelogByTag(options) {
|
|
7964
|
-
const gitCommits = await getGitCommits(options.from, options.to, options.scopeMap);
|
|
7965
|
-
const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, options.github);
|
|
7966
|
-
const md = generateMarkdown({ commits, options, showTitle: true, contributors });
|
|
7967
|
-
return md;
|
|
7968
|
-
}
|
|
7969
|
-
async function generateChangelogByTags(options) {
|
|
7970
|
-
const tags = getFromToTags(options.tags);
|
|
7971
|
-
const bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
|
|
7972
|
-
bar.start(tags.length, 0);
|
|
7973
|
-
let md = "";
|
|
7974
|
-
const resolvedLogins = /* @__PURE__ */ new Map();
|
|
7975
|
-
for await (const [index, tag] of tags.entries()) {
|
|
7976
|
-
const { from, to } = tag;
|
|
7977
|
-
const gitCommits = await getGitCommits(from, to, options.scopeMap);
|
|
7978
|
-
const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, options.github, resolvedLogins);
|
|
7979
|
-
const opts = { ...options, from, to };
|
|
7980
|
-
const nextMd = generateMarkdown({ commits, options: opts, showTitle: true, contributors });
|
|
7981
|
-
md = `${nextMd}
|
|
7982
|
-
|
|
7983
|
-
${md}`;
|
|
7984
|
-
bar.update(index + 1);
|
|
7985
|
-
}
|
|
7986
|
-
bar.stop();
|
|
7987
|
-
return md;
|
|
7988
|
-
}
|
|
7989
|
-
async function generateChangelog(total = false) {
|
|
7990
|
-
const options = await initOptions();
|
|
7991
|
-
let md = "";
|
|
7460
|
+
function genChangelog(total = false) {
|
|
7992
7461
|
if (total) {
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
}
|
|
7997
|
-
const isIn = await isVersionInMarkdown(options.to, options.output);
|
|
7998
|
-
if (!options.overrideChangelog && isIn) {
|
|
7999
|
-
return;
|
|
7462
|
+
generateTotalChangelog();
|
|
7463
|
+
} else {
|
|
7464
|
+
generateChangelog();
|
|
8000
7465
|
}
|
|
8001
|
-
md = await generateChangelogByTag(options);
|
|
8002
|
-
await writeMarkdown(md, options.output, false);
|
|
8003
|
-
}
|
|
8004
|
-
|
|
8005
|
-
async function genChangelog(total = false) {
|
|
8006
|
-
await generateChangelog(total);
|
|
8007
7466
|
}
|
|
8008
7467
|
|
|
8009
7468
|
async function release() {
|
|
@@ -8067,3 +7526,8 @@ Object.entries(commands).forEach(([command, { desc, action }]) => {
|
|
|
8067
7526
|
cli.command(command, desc).action(action);
|
|
8068
7527
|
});
|
|
8069
7528
|
cli.parse();
|
|
7529
|
+
function defineConfig(config) {
|
|
7530
|
+
return config;
|
|
7531
|
+
}
|
|
7532
|
+
|
|
7533
|
+
export { defineConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soybeanjs/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "SoybeanJS's command line tools",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Soybean",
|
|
@@ -32,23 +32,20 @@
|
|
|
32
32
|
"dist"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
+
"@soybeanjs/changelog": "0.0.2",
|
|
35
36
|
"bumpp": "9.1.0",
|
|
37
|
+
"c12": "1.4.1",
|
|
36
38
|
"cac": "6.7.14",
|
|
37
|
-
"cli-progress": "^3.12.0",
|
|
38
|
-
"convert-gitmoji": "0.1.3",
|
|
39
|
-
"dayjs": "1.11.8",
|
|
40
39
|
"enquirer": "2.3.6",
|
|
41
40
|
"execa": "7.1.1",
|
|
42
41
|
"kolorist": "1.8.0",
|
|
43
42
|
"lint-staged": "13.2.2",
|
|
44
43
|
"minimist": "1.2.8",
|
|
45
44
|
"npm-check-updates": "16.10.12",
|
|
46
|
-
"ofetch": "1.0.1",
|
|
47
45
|
"rimraf": "5.0.1"
|
|
48
46
|
},
|
|
49
47
|
"devDependencies": {
|
|
50
48
|
"@soybeanjs/cli": "link:",
|
|
51
|
-
"@types/cli-progress": "^3.11.0",
|
|
52
49
|
"@types/node": "20.2.5",
|
|
53
50
|
"eslint": "8.41.0",
|
|
54
51
|
"eslint-config-soybeanjs": "0.4.7",
|